﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace Plato
{
    public partial class ChartPanel : UserControl
    {
        public ChartPanel()
        {
            InitializeComponent();
        }

        #region 公共变量放置区
        private decimal ItemSpaceBetween = 0;//Item间距 
        private decimal ScaleSpaceBetween = 0;//刻度间距

        private decimal ControlWidth = 0;//控件宽度
        private decimal ControlHeight = 0;//控件高度
        private decimal WorkAreaWidth = 0;//宽度
        private decimal WorkAreaHeight = 0;//工作区域高度

        private decimal leftMultiple = 0;//左侧刻度倍数
        private decimal leftMaxValue = 0;//左侧刻度最大值
        private decimal rightMultiple = 0;//右侧刻度倍数
        private decimal rightMaxValue = 0;//右侧刻度最大值

        private decimal leftAvgScale = 0;
        private decimal rightAvgScale = 0;

        private int RowCount;
        //画笔定义区域
        Brush DrawCylinderBush;
        Brush DrawLinearlyBush;
        Brush DrawLinearlyIcoBush;
        Brush DrawTitleBrush;//标题Brush
        Brush DrawLinearlyValueBrush;//线性数值Brush
        Brush DrawCylinderValueBrush;//柱状图数值Brush
        private Pen DrawFormBorderPen;//绘制图表边框Pen
        private Pen DrawFillLinePen;//绘制构造线Pen


        string[] ItemData = { "abc", "bcd", "cde", "def", "efg", "fgh", "ghi", "hij", "ijk", "jkl" };
        decimal[] LeftData = { 40, 60, 34, 73, 90, 50, 54, 89, 55, 75 };
        decimal[] RightData = { 0.5m, 0.56m, 0.34m, 0.73m, 0.98m, 0.68m, 0.54m, 0.89m, 0.55m, 0.75m };



        #endregion

        private void ChartPanel_Paint(object sender, PaintEventArgs e)
        {
            //控件绘制事件
            ControlWidth = this.Width;
            ControlHeight = this.Height;

            WorkAreaHeight = this.ControlHeight - this.topPadding - this.bottomPadding;
            WorkAreaWidth = this.ControlWidth - this.leftPadding - this.rightPadding;

            DrawCylinderBush = new SolidBrush(cylinderColor);//绘制柱状图Bar颜色初始化
            DrawLinearlyBush = new SolidBrush(linearlyColor);//绘制线性图Line颜色初始化
            DrawLinearlyIcoBush = new SolidBrush(linearlyIcoColor);//绘制线性图Ico颜色初始化
            DrawTitleBrush = new SolidBrush(titleColor);//标题Brush初始化

            DrawFormBorderPen = new Pen(formBorderColor, formBorderSize);//绘制主框架Pen初始化
            DrawFillLinePen = new Pen(displayFillLineColor, 1);//绘制框架参考线Pen初始化
            DrawFillLinePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
            DrawFillLinePen.DashPattern = new float[] { 5, 5 };

            DrawLinearlyValueBrush = new SolidBrush(linearlyValueColor);//线性图Value颜色
            DrawCylinderValueBrush = new SolidBrush(cylinderValueColor);//柱状图Value颜色

            DrawFrameWork(e.Graphics);

            AnaliysisDataSource();
            if (RowCount <= 0) return;

            ItemSpaceBetween = (decimal)(WorkAreaWidth / (RowCount * 2 + 1));//获取每个柱状图的间距及宽度
            ScaleSpaceBetween = (decimal)(WorkAreaHeight / (scaleQuantity + 1));//获取刻度间距

            leftMaxValue = Method.GetMaxValue(LeftData);//获取左边数据的最大值
            leftMultiple = Method.GetMultiples(leftMaxValue);//获取左边数据的倍数
            rightMaxValue = Method.GetMaxValue(RightData);//获取右边数据的最大值
            rightMultiple = Method.GetMultiples(rightMaxValue);//获取右边数据的最大值

            int tmpLeftScale = 0;
            int tmpRightScale = 0;
  
                tmpLeftScale = (int)(leftMaxValue / (1 / leftMultiple));
                if ((int)(leftMaxValue % (1 / leftMultiple)) != 0) tmpLeftScale += 1;
                _LeftMaxScale = (decimal)tmpLeftScale / leftMultiple;
    

                tmpRightScale = (int)(rightMaxValue / (1 / rightMultiple));
                if ((int)(rightMaxValue % (1 / rightMultiple)) != 0) tmpRightScale += 1;
                _RightMaxScale = (decimal)tmpRightScale / rightMultiple;
            
            this.leftAvgScale = (this._LeftMaxScale - this._LeftMinScale) / (decimal)this.scaleQuantity;
            this.rightAvgScale = (this._RightMaxScale - this._RightMinScale) / (decimal)this.scaleQuantity;

            e.Graphics.DrawString(titleText, titleFont, new SolidBrush(titleColor), titleLocate);

            DrawScale(e.Graphics);
            DrawCylinderChart(e.Graphics);
            DrawLinearlyChart(e.Graphics);
            DrawItems(e.Graphics);
        }

        private void ChartPanel_Resize(object sender, EventArgs e)
        {
            //控件调整大小事件
            Invalidate();
        }

        /// <summary>
        /// 传入数据分析
        /// </summary>
        private void AnaliysisDataSource()
        {
            try
            {
                RowCount = dataSource.Rows.Count;
                ItemData = new string[RowCount];
                LeftData = new decimal[RowCount];
                RightData = new decimal[RowCount];
                for (int i = 0; i < RowCount; i++)
                {
                    ItemData[i] = Convert.ToString(dataSource.Rows[i][itemValueIndex]);
                    LeftData[i] = (decimal)Convert.ToDouble(dataSource.Rows[i][cylinderIndex]);
                    RightData[i] = (decimal)Convert.ToDouble(dataSource.Rows[i][linearlyIndex]);
                }
            }
            catch (Exception e)
            { throw e; }
        }

        /// <summary>
        /// 框架绘制
        /// </summary>
        private void DrawFrameWork(Graphics g)
        {

            #region 绘制主框架
            g.DrawRectangle(DrawFormBorderPen, (float)leftPadding, (float)topPadding, (float)WorkAreaWidth, (float)WorkAreaHeight);
            #endregion
        }

        /// <summary>
        /// 绘制柱状图
        /// </summary>
        /// <param name="g"></param>
        private void DrawCylinderChart(Graphics g)
        {
            //绘制条形图
            decimal lX = leftPadding + ItemSpaceBetween;
            decimal lY = ControlHeight - bottomPadding;

            for (int i = 0; i < RowCount; i++)
            {
                decimal tmpY = (LeftData[i] / leftAvgScale * ScaleSpaceBetween) * ((_LeftMaxScale - _LeftMinScale) / _LeftMaxScale);
                g.FillRectangle(DrawCylinderBush, (float)lX, (float)(lY - tmpY), (float)ItemSpaceBetween, (float)tmpY);
                g.DrawString(LeftData[i].ToString(), cylinderValueFont, DrawCylinderValueBrush, (float)(lX + cylinderValueLocate.X), (float)(ControlHeight - bottomPadding - cylinderValueLocate.Y));
                lX += ItemSpaceBetween * 2;
            }
            //绘制图标样式
            g.FillRectangle(DrawCylinderBush, _CylinederIcoLocale.X + 60, _CylinederIcoLocale.Y + 5, 40, 5);
            g.DrawString(_IcoText[cylinderIndex - 1], _IcoFont, new SolidBrush(_IcoColor), _CylinederIcoLocale);
        }

        private void DrawLinearlyChart(Graphics g)
        {
            //绘制线性图
            decimal x = ItemSpaceBetween + leftPadding;
            decimal xCenter = ItemSpaceBetween / 2;
            decimal x1, y1;
            x1 = x + xCenter;
            y1 = ControlHeight - bottomPadding - (RightData[0] / rightAvgScale * ScaleSpaceBetween) * ((_RightMaxScale - _RightMinScale) / _RightMaxScale);
            g.FillEllipse(DrawLinearlyIcoBush, (float)x1 - 2.5f, (float)y1 - 2.5f, 5f, 5f);
            g.DrawString(RightData[0].ToString(), linearlyValueFont, DrawLinearlyIcoBush, (float)(x1 - linearlyValueLocate.X), (float)(y1 - linearlyValueLocate.Y));
            for (int i = 1; i < RowCount; i++)
            {
                decimal x2, y2;
                x2 = x1 + xCenter * 2 + ItemSpaceBetween;
                y2 = ControlHeight - bottomPadding - (RightData[i] / rightAvgScale * ScaleSpaceBetween) * ((_RightMaxScale - _RightMinScale) / _RightMaxScale);
                g.DrawLine(new Pen(linearlyColor, 1), (float)x1, (float)y1, (float)x2, (float)y2);
                x1 = x2;
                y1 = y2;
                g.FillEllipse(DrawLinearlyIcoBush, (float)x1 - 2.5f, (float)y1 - 2.5f, 5f, 5f);
                g.DrawString(RightData[i].ToString(), linearlyValueFont, DrawLinearlyIcoBush, (float)(x1 - linearlyValueLocate.X), (float)(y1 - linearlyValueLocate.Y));
            }
            //绘制图标样式
            g.DrawLine(new Pen(linearlyColor, 1), _LinearlyIcoLocate.X + 60, _LinearlyIcoLocate.Y + 6, _LinearlyIcoLocate.X + 100, _LinearlyIcoLocate.Y + 6);
            g.DrawString(_IcoText[linearlyIndex - 1], _IcoFont, new SolidBrush(_IcoColor), _LinearlyIcoLocate);
            g.FillEllipse(DrawLinearlyIcoBush, _LinearlyIcoLocate.X + 80, _LinearlyIcoLocate.Y + 3, 6, 6);
        }

        private void DrawItems(Graphics g)
        {
            for (int i = 0; i < RowCount; i++)
            {
                g.DrawString(ItemData[i], itemValueFont, new SolidBrush(itemValueColor), (float)(leftPadding + i * ItemSpaceBetween + (i + 1) * ItemSpaceBetween + itemValueLocate.X), (float)(ControlHeight - 20 + itemValueLocate.Y));
            }
        }

        /// <summary>
        /// 绘制刻度
        /// </summary>
        /// <param name="g"></param>
        private void DrawScale(Graphics g)
        {
            decimal leftPointX = leftPadding;
            decimal leftPointY = ControlHeight - bottomPadding;
            decimal rightPointX = ControlWidth - rightPadding;
            decimal rightPointY = ControlHeight - bottomPadding;
            g.DrawString(_LeftMinScale.ToString(), scaleFont, DrawLinearlyIcoBush, (float)scaleLeftLocate.X, (float)leftPointY - (float)scaleLeftLocate.Y);
            //绘制右边刻度
            g.DrawString(_RightMinScale.ToString(), scaleFont, DrawLinearlyIcoBush, (float)rightPointX + (float)scaleRightLocate.X, (float)rightPointY - (float)scaleRightLocate.Y);
            for (int i = 0; i <= scaleQuantity; i++)
            {
                g.DrawLine(new Pen(scaleColor, 1), (float)leftPointX, (float)leftPointY, (float)(leftPointX - 10), (float)leftPointY);//Left scale
                g.DrawLine(new Pen(scaleColor, 1), (float)rightPointX, (float)rightPointY, (float)(rightPointX + 10), (float)rightPointY);//right scale
                if (isDisplayFillLine && i > 0)
                {
                    g.DrawLine(DrawFillLinePen, (float)leftPointX, (float)leftPointY, (float)rightPointX, (float)rightPointY);//参考线
                    //绘制左边刻度
                }
                g.DrawString((_LeftMinScale + leftAvgScale * (decimal)i).ToString(), scaleFont, DrawLinearlyIcoBush, (float)scaleLeftLocate.X, (float)leftPointY - (float)scaleLeftLocate.Y);
                //绘制右边刻度
                g.DrawString((_RightMinScale + rightAvgScale * (decimal)i).ToString(), scaleFont, DrawLinearlyIcoBush, (float)rightPointX + (float)scaleRightLocate.X, (float)rightPointY - (float)scaleRightLocate.Y);
                leftPointY -= ScaleSpaceBetween;
                rightPointY -= ScaleSpaceBetween;
            }

        }

        #region 数据设置
        private DataTable dataSource = new DataTable();
        [Browsable(true), Category("图表数据设置"), Description("设置图表数据源")]
        public DataTable DataSource
        {
            get { return dataSource; }
            set
            {
                dataSource = value;
                Invalidate();
                Invalidate();
            }
        }
        #endregion

        #region 图表样式设置
        private decimal topPadding = 100;//顶部边距
        [Browsable(true),Category("图表样式设置"),Description("顶部边距")]
        public decimal TopPadding
        {
            get { return topPadding; }
            set { topPadding = value; Invalidate(); }
        }

        private decimal leftPadding = 50;//左边边距
        [Browsable(true), Category("图表样式设置"), Description("左边边距")]
        public decimal LeftPadding
        {
            get { return leftPadding; }
            set { leftPadding = value; Invalidate(); }
        }
        
        private decimal rightPadding = 50;//右边边距
        [Browsable(true), Category("图表样式设置"), Description("右边边距")]
        public decimal RightPadding
        {
            get { return rightPadding; }
            set { rightPadding = value; Invalidate(); }
        }
        
        private decimal bottomPadding = 50;//底部边距
        [Browsable(true), Category("图表样式设置"), Description("底部边距")]
        public decimal BottomPadding
        {
            get { return bottomPadding; }
            set { bottomPadding = value; Invalidate(); }
        }

        private int formBorderSize = 1;
        [Browsable(true), Category("图表样式设置"), Description("设置图表边框Size")]
        public int FormBorderSize
        {
            get { return formBorderSize; }
            set
            {
                if (value < 1) formBorderSize = 1;
                else formBorderSize = value;
                Invalidate();
            }
        }

        private Color formBorderColor = Color.Black;
        [Browsable(true), Category("图表样式设置"), Description("设置图表边框Color")]
        public Color FormBorderColor
        {
            get { return formBorderColor; }
            set { formBorderColor = value; Invalidate(); }
        }

        private bool isDisplayFillLine = true;
        [Browsable(true), Category("图表样式设置"), Description("设置图表是否显示参照线")]
        public bool IsDisplayFillLine
        {
            get { return isDisplayFillLine; }
            set
            {
                isDisplayFillLine = value;
                Invalidate();
            }
        }

        private Color displayFillLineColor = Color.LightGray;
        [Browsable(true), Category("图表样式设置"), Description("设置图表参照线Color")]
        public Color DisplayFillLineColor
        {
            get { return displayFillLineColor; }
            set
            {
                displayFillLineColor = value; 
                Invalidate();
            }
        }
        #endregion

        #region 标题属性设置

        private string titleText = "Plato";
        [Browsable(true), Category("图表标题设置"), Description("标题内容")]
        public string TitleText
        {
            get { return titleText; }
            set
            {
                titleText = value;
                Invalidate();
            }
        }

        private Point titleLocate = new Point(5, 5);
        [Browsable(true), Category("图表标题设置"), Description("标题位置")]
        public Point TitleLocate
        {
            get { return titleLocate; }
            set
            {
                titleLocate = value;
                Invalidate();
            }
        }

        private Font titleFont = new Font("宋体", 12);
        [Browsable(true), Category("图表标题设置"), Description("标题字体")]
        public Font TitleFont
        {
            get { return titleFont; }
            set
            {
                titleFont = value;
                Invalidate();
            }
        }

        private Color titleColor = Color.Black;
        [Browsable(true), Category("图表标题设置"), Description("标题内容颜色")]
        public Color TitleColor1
        {
            get { return titleColor; }
            set
            {
                titleColor = value;
                Invalidate();
            }
        }

        #endregion

        #region 刻度样式设置

        private int scaleQuantity = 10;
        [Browsable(true), Category("刻度样式设置"), Description("设置刻度显示数量")]
        public int ScaleQuantity
        {
            get { return scaleQuantity; }
            set
            {
                scaleQuantity = value;
                Invalidate();
            }
        }

        private Color scaleColor = Color.Black;
        [Browsable(true), Category("刻度样式设置"), Description("设置刻度显示颜色")]
        public Color ScaleColor
        {
            get { return scaleColor; }
            set
            {
                scaleColor = value;
                Invalidate();
            }
        }

        private int scaleBorderSize = 1;
        [Browsable(true), Category("刻度样式设置"), Description("设置刻度显示线宽")]
        public int ScaleBorderSize
        {
            get { return scaleBorderSize; }
            set
            {
                scaleBorderSize = value;
                Invalidate();
            }
        }

        private Font scaleFont = new Font("宋体", 10);
        [Browsable(true), Category("刻度样式设置"), Description("设置刻度显示字体")]
        public Font ScaleFont
        {
            get { return scaleFont; }
            set
            {
                scaleFont = value;
                Invalidate();
            }
        }

        private Point scaleLeftLocate = new Point(5, 5);
        [Browsable(true), Category("刻度样式设置"), Description("设置左侧刻度显示位置")]
        public Point ScaleLeftLocate
        {
            get { return scaleLeftLocate; }
            set
            {
                scaleLeftLocate = value;
                Invalidate();
            }
        }

        private Point scaleRightLocate = new Point(5, 5);
        [Browsable(true), Category("刻度样式设置"), Description("设置右侧刻度显示位置")]
        public Point ScaleRightLocate
        {
            get { return scaleRightLocate; }
            set
            {
                scaleRightLocate = value;
                Invalidate();
            }
        }

        private decimal _LeftMaxScale = 0;//左侧最大刻度
        [Browsable(true), Category("刻度样式设置"), Description("设置左侧最大刻度")]
        public decimal LeftMaxScale
        {
            get { return _LeftMaxScale; }
            set
            {
                _LeftMaxScale = value;
                Invalidate();
            }
        }

        private decimal _LeftMinScale = 0;//左侧最小刻度
        [Browsable(true), Category("刻度样式设置"), Description("设置左侧最小刻度")]
        public decimal LeftMinScale
        {
            get { return _LeftMinScale; }
            set
            {
                _LeftMinScale = value;
                Invalidate();
            }
        }

        private decimal _RightMaxScale = 0;//右侧最大刻度
        [Browsable(true), Category("刻度样式设置"), Description("设置右侧最大刻度")]
        public decimal RightMaxScale
        {
            get { return _RightMaxScale; }
            set
            {
                _RightMaxScale = value;
                Invalidate();
            }
        }

        private decimal _RightMinScale = 0;//右侧最小刻度
        [Browsable(true), Category("刻度样式设置"), Description("设置右侧最小刻度")]
        public decimal RightMinScale
        {
            get { return _RightMinScale; }
            set
            {
                _RightMinScale = value;
                Invalidate();
            }
        }

        #endregion

        #region 条形图样式设置

        int cylinderIndex = 1;
        [Browsable(true), Category("条形图样式设置"), Description("设置图表柱状图数据索引")]
        public int CylinderIndex
        {
            get { return this.cylinderIndex; }
            set
            {
                this.cylinderIndex = value; 
                Invalidate();
            }
        }

        private Color cylinderColor = Color.Blue;
        [Browsable(true), Category("条形图样式设置"), Description("设置图表柱状图颜色")]
        public Color CylinderColor
        {
            get { return cylinderColor; }
            set
            {
                cylinderColor = value; 
                Invalidate();
            }
        }

        private Font cylinderValueFont = new Font("宋体", 8);
        [Browsable(true), Category("条形图样式设置"), Description("设置图表柱状图Value字体")]
        public Font CylinderValueFont
        {
            get { return cylinderValueFont; }
            set
            {
                cylinderValueFont = value;
                Invalidate();
            }
        }

        private Color cylinderValueColor = Color.Blue;
        [Browsable(true), Category("条形图样式设置"), Description("设置图表柱状图数Value的字体颜色")]
        public Color CylinderValueColor
        {
            get { return cylinderValueColor; }
            set
            {
                cylinderValueColor = value;
                Invalidate();
            }
        }

        private Point cylinderValueLocate = new Point(5, 5);
        [Browsable(true), Category("条形图样式设置"), Description("设置图表柱状图数Value的位置")]
        public Point CylinderValueLocate
        {
            get { return cylinderValueLocate; }
            set
            {
                cylinderValueLocate = value;
                Invalidate();
            }
        }

        #endregion

        #region 线性图样式设置

        int linearlyIndex = 2;
        [Browsable(true), Category("线性图样式设置"), Description("设置图表线性图数据索引")]
        public int LinearlyIndex
        {
            get { return this.linearlyIndex; }
            set
            {
                this.linearlyIndex = value; 
                Invalidate();
            }
        }

        private Color linearlyColor = Color.Red;
        [Browsable(true), Category("线性图样式设置"), Description("设置图表线性图颜色")]
        public Color LinearlyColor
        {
            get { return linearlyColor; }
            set
            {
                linearlyColor = value;
                Invalidate();
            }
        }

        private Color linearlyIcoColor = Color.Red;
        [Browsable(true), Category("线性图样式设置"), Description("设置图表线性图图标颜色")]
        public Color LinearlyIcoColor
        {
            get { return linearlyIcoColor; }
            set { linearlyIcoColor = value; Invalidate(); }
        }

        private Font linearlyValueFont = new Font("宋体", 8);
        [Browsable(true), Category("线性图样式设置"), Description("设置线性图Value字体")]
        public Font LinearlyValueFont
        {
            get { return linearlyValueFont; }
            set
            {
                linearlyValueFont = value;
                Invalidate();
            }
        }

        private Point linearlyValueLocate = new Point(5, 5);
        [Browsable(true), Category("线性图样式设置"), Description("设置线性图Value位置")]
        public Point LinearlyValueLocate
        {
            get { return linearlyValueLocate; }
            set
            {
                linearlyValueLocate = value;
                Invalidate();
            }
        }

        private Color linearlyValueColor = Color.Red;
        [Browsable(true), Category("线性图样式设置"), Description("设置图表线性图数值字体Color")]
        public Color LinearlyValueColor
        {
            get { return linearlyValueColor; }
            set
            {
                linearlyValueColor = value; 
                Invalidate();
            }
        }

        #endregion

        #region Item样式设定

        private int itemValueIndex = 0;
        [Browsable(true), Category("枚举项设置"), Description("设置枚举项数据索引")]
        public int ItemValueIndex
        {
            get { return itemValueIndex; }
            set { itemValueIndex = value; }
        }

        private Font itemValueFont = new Font("宋体", 8);
        [Browsable(true), Category("枚举项设置"), Description("设置枚举项字体")]
        public Font ItemValueFont
        {
            get { return itemValueFont; }
            set
            {
                itemValueFont = value;
                Invalidate();
            }
        }

        private Color itemValueColor = Color.Black;
        [Browsable(true), Category("枚举项设置"), Description("设置枚举项字体颜色")]
        public Color ItemValueColor
        {
            get { return itemValueColor; }
            set
            {
                itemValueColor = value;
                Invalidate();
            }
        }

        private Point itemValueLocate = new Point(5, 5);
        [Browsable(true), Category("枚举项设置"), Description("设置枚举项显示位置")]
        public Point ItemValueLocate
        {
            get { return itemValueLocate; }
            set
            {
                itemValueLocate = value;
                Invalidate();
            }
        }
        
        
        #endregion

        #region 图例标示设置
        private string[] _IcoText ={ "销售数量", "销售总额" };
        [Browsable(true), Category("图例标示设置"), Description("图例标示内容")]
        public string[] IcoText
        {
            get { return _IcoText; }
            set
            {
                _IcoText = value;
                Invalidate();
            }
        }

        private Point _CylinederIcoLocale = new Point(5, 25);
        [Browsable(true), Category("图例标示设置"), Description("条形图图例标示位置")]
        public Point CylinederIcoLocale
        {
            get { return _CylinederIcoLocale; }
            set
            {
                _CylinederIcoLocale = value;
                Invalidate();
            }
        }

        private Point _LinearlyIcoLocate = new Point(5, 45);
        [Browsable(true), Category("图例标示设置"), Description("线性图图例标示位置")]
        public Point LinearlyIcoLocate
        {
            get { return _LinearlyIcoLocate; }
            set
            {
                _LinearlyIcoLocate = value;
                Invalidate();
            }
        }

        private Font _IcoFont = new Font("Arial", 8);
        [Browsable(true), Category("图例标示设置"), Description("图例标示字体")]
        public Font IcoFont
        {
            get { return _IcoFont; }
            set
            {
                _IcoFont = value;
                Invalidate();
            }
        }

        private Color _IcoColor = Color.Black;
        [Browsable(true), Category("图例标示设置"), Description("图例标示字体颜色")]
        public Color IcoColor
        {
            get { return _IcoColor; }
            set
            {
                _IcoColor = value;
                Invalidate();
            }
        }

        #endregion

    }
}
